package com.seabook.calparser.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.filters.NodeClassFilter;
import org.htmlparser.filters.OrFilter;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.tags.TableColumn;
import org.htmlparser.tags.TableRow;
import org.htmlparser.tags.TableTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
import org.htmlparser.visitors.HtmlPage;

import com.seabook.calparser.pojo.CalReport;
import com.seabook.calparser.pojo.StatusAndLogLink;

public class CalParser {

	private static Map<Integer, String> paramMapping = new HashMap<Integer, String>();

	static {
		paramMapping.put(0, "simiErrInProd");
		paramMapping.put(1, "classification");
		paramMapping.put(2, "envIssue");
		paramMapping.put(3, "pool");
		paramMapping.put(4, "url");
		paramMapping.put(5, "statusAndLogLink");
		paramMapping.put(6, "count");
		paramMapping.put(7, "exceptionType");
		paramMapping.put(8, "exceptionName");
		paramMapping.put(9, "rank");
	}

	public CalParser() {
	}

	// public void initialize() {
	// url = uriBuilder.buildURL();
	// System.out.println("url: ==> " + url);
	// try {
	// parser = new Parser(url);
	// } catch (ParserException e) {
	// e.printStackTrace();
	// throw new RuntimeException(e.getMessage());
	// }
	// }

	public static List<CalReport> parseCalLogs(Parser parser) {
		List<CalReport> calReportList = new ArrayList<CalReport>();
		String inputHTML = getTableHtmlFromPage(parser);
		try {
			parser.setInputHTML(inputHTML);
		} catch (ParserException e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		NodeFilter tableFilter = new NodeClassFilter(TableTag.class);
		OrFilter lastFilter = new OrFilter();
		lastFilter.setPredicates(new NodeFilter[] { tableFilter });
		NodeList nodeList = null;
		try {
			nodeList = parser.parse(lastFilter);
		} catch (ParserException e) {
			e.printStackTrace();
		}

		BeanInfo info = null;
		try {
			info = Introspector.getBeanInfo(CalReport.class);
		} catch (IntrospectionException e) {
			e.printStackTrace();
		}
		for (int i = 0; i <= nodeList.size(); i++) {
			if (nodeList.elementAt(i) instanceof TableTag) {
				TableTag tag = (TableTag) nodeList.elementAt(i);
				TableRow[] rows = tag.getRows();
				for (int j = 1; j < rows.length; j++) {
					CalReport calReport = new CalReport();
					TableRow tr = (TableRow) rows[j];
					TableColumn[] td = tr.getColumns();
					for (int k = 0; k < td.length; k++) {
						TableColumn column = td[k];
						String text = column.toPlainTextString();
						String param = paramMapping.get(k);
						for (PropertyDescriptor pd : info
								.getPropertyDescriptors()) {
							if ("statusAndLogLink".equals(param)) {
								String link = extractLogview(column.toHtml(), parser);
								if (text.contains("[Logview]")) {
									text = text.substring(0, text.indexOf("[Logview]"));
								}
								StatusAndLogLink statusAndLogLink = new StatusAndLogLink(text, link);
								calReport.setStatusAndLogLink(statusAndLogLink);
							} else if (pd.getName().equals(param)) {
								try {
									pd.getWriteMethod().invoke(calReport, text);
								} catch (IllegalArgumentException e) {
									e.printStackTrace();
								} catch (IllegalAccessException e) {
									e.printStackTrace();
								} catch (InvocationTargetException e) {
									e.printStackTrace();
								}
							}
						}
					}
					calReportList.add(calReport);
				}
			}
		}
		
		return calReportList;
	}

	private static String getTableHtmlFromPage(Parser parser) {
		HtmlPage page = null;
		try {
			page = new HtmlPage(parser);
			parser.visitAllNodesWith(page);
		} catch (ParserException e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}

		TableTag[] tableTags = page.getTables();

		for (TableTag tag : tableTags) {
			TableRow[] rows = tag.getRows();
			for (TableRow row : rows) {
				TableColumn[] columns = row.getColumns();
				for (TableColumn column : columns) {
					if ("Similar Error in Production:".equals(column
							.toPlainTextString())) {
						return tag.toHtml();
					}
				}
			}
		}
		throw new RuntimeException("No Cal Log Matched Content Found!!!");
	}

	private static String extractLogview(String inputHTML, Parser parser) {
		String logviewLink = "";
		try {
			parser.setInputHTML(inputHTML);
		} catch (ParserException e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		NodeFilter linkFilter = new NodeClassFilter(LinkTag.class);
		NodeList nodeList = null;
		try {
			nodeList = parser.extractAllNodesThatMatch(linkFilter);
		} catch (ParserException e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		for (int i = 0; i < nodeList.size(); i++) {
			LinkTag node = (LinkTag) nodeList.elementAt(i);
			logviewLink = node.extractLink();
		}
		return logviewLink;
	}

}
